#ifndef _FDC_
#define _FDC_

/* hardware datatypes */
typedef unsigned char BYTE;           /* 8-bit byte */
typedef unsigned short WORD;          /* 16-bit word */
typedef unsigned long DWORD;          /* 32-bit dword */
typedef unsigned long ADDR;           /* address that should not be deref'd */

/* integer types */
typedef unsigned char UINT8;          /* 8-bit unsigned integer */
typedef signed char INT8;             /* 8-bit signed integer */
typedef unsigned short UINT16;        /* 16-bit unsigned integer */
typedef signed short INT16;           /* 16-bit signed integer */
typedef unsigned long UINT32;         /* 32-bit unsigned integer */
typedef signed long INT32;            /* 32-bit signed integer */ 
 
/* logical datatypes */
typedef unsigned char CHAR;           /* ISO 8859-1 character */
typedef unsigned char *STRPTR;        /* C-style NUL-terminated string */
typedef enum { FALSE=0,TRUE=1 } BOOL; /* boolean value */

/* constants */

/* useful macros */
#define BITFIELD(name,width) unsigned int name : width
#define HIBYTE(x) ((BYTE)((x) >> 8))
#define LOBYTE(x) ((BYTE)((x) & 0xff))
#define ABS(x) ((x) < 0 ? -(x) : (x))    /* NB: multiple evaluations! */

/* datatypes */

/* drive geometry */
typedef struct DrvGeom {
   BYTE heads;
   BYTE tracks;
   BYTE spt;     /* sectors per track */
} DrvGeom;

/* drive geometries */
#define DG144_HEADS       2     /* heads per drive (1.44M) */
#define DG144_TRACKS     80     /* number of tracks (1.44M) */
#define DG144_SPT        18     /* sectors per track (1.44M) */
#define DG144_GAP3FMT  0x54     /* gap3 while formatting (1.44M) */
#define DG144_GAP3RW   0x1b     /* gap3 while reading/writing (1.44M) */

#define DG168_HEADS       2     /* heads per drive (1.68M) */
#define DG168_TRACKS     80     /* number of tracks (1.68M) */
#define DG168_SPT        21     /* sectors per track (1.68M) */
#define DG168_GAP3FMT  0x0c     /* gap3 while formatting (1.68M) */
#define DG168_GAP3RW   0x1c     /* gap3 while reading/writing (1.68M) */

/* IO ports */
#define FDC_DOR  (0x3f2)   /* Digital Output Register */
#define FDC_MSR  (0x3f4)   /* Main Status Register (input) */
#define FDC_DRS  (0x3f4)   /* Data Rate Select Register (output) */
#define FDC_DATA (0x3f5)   /* Data Register */
#define FDC_DIR  (0x3f7)   /* Digital Input Register (input) */
#define FDC_CCR  (0x3f7)   /* Configuration Control Register (output) */

/* command bytes (these are 765 commands + options such as MFM, etc) */
#define CMD_SPECIFY (0x03)  /* specify drive timings */
#define CMD_WRITE   (0xc5)  /* write data (+ MT,MFM) */
#define CMD_READ    (0xe6)  /* read data (+ MT,MFM,SK) */
#define CMD_RECAL   (0x07)  /* recalibrate */
#define CMD_SENSEI  (0x08)  /* sense interrupt status */
#define CMD_FORMAT  (0x4d)  /* format track (+ MFM) */
#define CMD_SEEK    (0x0f)  /* seek track */
#define CMD_VERSION (0x10)  /* FDC version */

typedef struct DmaChannel {
   BYTE page;     /* page register */
   BYTE offset;   /* offset register */
   BYTE length;   /* length register */
} DmaChannel;
void dma_xfer(int channel,long physaddr,int length,BOOL read);



/* function prototypes */

void init();

int reset(void);
BOOL diskchange(void);
void motoron(void);
void motoroff(void);
void recalibrate(void);
BOOL seek(int track);
BOOL log_disk(DrvGeom *g);
BOOL read_block(int block,BYTE *blockbuff);
BOOL write_block(int block,BYTE *blockbuff);
BOOL format_track(BYTE track,DrvGeom *g);

extern inline BYTE inb(UINT16 port)
{
   register BYTE data;
   asm volatile ("inb %1,%0" : "=a" (data) : "d" (port));
   return data;
}

extern inline void outb(UINT16 port,BYTE data)
{
   asm volatile ("outb %1,%0" : : "d" (port),"a" (data));
}

extern inline WORD inw(UINT16 port)
{
   register WORD data;
   asm volatile ("inw %1,%0" : "=a" (data) : "d" (port));
   return data;
}

extern inline void outw(UINT16 port,WORD data)
{
   asm volatile ("outw %1,%0" : : "d" (port),"a" (data));
}

extern inline void wfill(WORD *start,UINT32 size,WORD value)
{
   asm volatile ("cld\n"
		 "\trep\n"
		 "\tstosw"
		 : /* no outputs */
		 : "D"(start),"c"(size),"a"(value)
		 : "%edi","%ecx");
}


#endif
